package cn.tedu.order.tcc;


import cn.tedu.common.tcc.ResultHolder;
import cn.tedu.order.entity.Order;
import cn.tedu.order.mapper.OrderMapper;
import io.seata.rm.tcc.api.BusinessActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
@Component
public class OrderTccActionImpl implements OrderTccAction {
    @Autowired
    private OrderMapper orderMapper;


    //1.一阶段失败，没有标记，回滚不执行
    //2.一阶段成功，有成功标记，其他模块执行失败，可以执行回滚，回滚完成删除标记
    @Transactional
    @Override
    public boolean prepare(BusinessActionContext ctx, Long id, Long userId, Long productId, Integer count, BigDecimal money) {
        orderMapper.createFrozen(new Order(id, userId, productId, count, money, 0));
        //true表示操作成功，反之操作失败
        /*第一阶段成功时，设置成功标记 Action类--事务id--“p”
        * 添加此标记做幂等性控制
        * */
        ResultHolder.setResult(OrderTccAction.class, ctx.getXid(), "p");
        return true;
    }
    @Transactional
    @Override
    /*加synchronized避免多个线程同时提交造成数据出错*/
    public synchronized boolean commit(BusinessActionContext ctx) {
        /*二阶段执行前先检查标记是否存在，若存在，执行第二步，若不存在，则不执行*/
        if (ResultHolder.getResult(OrderTccAction.class, ctx.getXid() ) == null) {
            return true;
        }
        Long orderId = Long.valueOf(ctx.getActionContext("orderId").toString());

        orderMapper.updateStatus(orderId,1);
        /*二阶段完成后删除标记，防止重复执行此操作*/
        ResultHolder.removeResult(OrderTccAction.class, ctx.getXid());
        return true;
    }
    @Transactional
    @Override
    public synchronized boolean rollback(BusinessActionContext ctx) {
        /*rollback阶段执行前先检查标记是否存在，若存在，执行rollback，若不存在，则不执行*/
        //一阶段失败，没有标记，回滚不执行
        if (ResultHolder.getResult(OrderTccAction.class, ctx.getXid() ) == null) {
            return true;
        }
        Long orderId = Long.valueOf(ctx.getActionContext("orderId").toString());
        orderMapper.deleteById(orderId);
        /*rollback执行完成后删除标记，防止重复执行此操作*/
        ResultHolder.removeResult(OrderTccAction.class, ctx.getXid());
        return true;
    }
}
